package org.sxp.modules.datasource.controller;

import java.util.*;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.sxp.common.dto.DatabaseDTO;
import org.sxp.common.enums.DbTypeEnum;
import org.sxp.common.exception.BusinessException;
import org.sxp.common.utils.*;
import org.sxp.modules.datasource.entity.DatabaseDO;
import org.sxp.modules.datasource.service.DatabaseService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.sxp.common.annotation.SysLog;
import org.sxp.common.web.WrapperResponse;
import org.sxp.modules.sys.controller.AbstractController;
import org.apache.shiro.authz.annotation.RequiresPermissions;

/**
 * 
 * @author 沈兴平
 * @date 2021/12/30
 */
@RestController
@RequestMapping(value = "/datasource/database")
@Api(description="Database", tags = "")
@SysLog(modules = "datasource", value = "")
public class DatabaseController extends AbstractController{
    public static final String UPDATE = "update";
    public static final String DELETE = "delete";
    public static final String INSERT = "insert";
    @Autowired
    private DatabaseService databaseService;

    /**
     * 列表
     */
    @ApiImplicitParams({
            @ApiImplicitParam(name="pageNum", value = "当前页码", dataType="int", paramType = "header"),
            @ApiImplicitParam(name="pageSize",value="每页条目",dataType="int", paramType = "header"),
            @ApiImplicitParam(name="orderField",value="排序字段",dataType="string", paramType = "header"),
            @ApiImplicitParam(name="orderType",value="排序类型",dataType="string", paramType = "header", example = "asc或者desc")
    })
    @RequestMapping(value = "/list",method = {RequestMethod.POST})
    @ApiOperation(value = "查询列表")
    @RequiresPermissions("datasource:database:list")
    public WrapperResponse<List<DatabaseDTO>> list(DatabaseDTO params) throws Exception{
        //请求头获取分页参数
        PageInfo pageInfo = buildPageInfo();
        IPage<DatabaseDO> page = databaseService.page(
                new Query<DatabaseDO>().getPage(pageInfo),
                new LambdaQueryWrapper<DatabaseDO>()
                        .eq(DatabaseDO::getSpaceId, params.getSpaceId())
                        .eq(StrUtil.isNotBlank(params.getId()), DatabaseDO::getId, params.getId())
                        .eq(StrUtil.isNotBlank(params.getType()), DatabaseDO::getType, params.getType())
        );

        for(DatabaseDO databaseDO : page.getRecords()){
            databaseDO.setTypeName(DbTypeEnum.getType(databaseDO.getType()).name());
        }
        return (WrapperResponse)WrapperResponse.success(new PageResult(page));
    }


    /**
     * 信息
     */
    @RequestMapping(value = "/info/{id}", method = {RequestMethod.GET})
    @ApiOperation(value = "查询")
    @RequiresPermissions("datasource:database:info")
    public WrapperResponse<DatabaseDTO> info(@PathVariable String id) throws Exception{
        DatabaseDO database = databaseService.getById(id);
        DatabaseDTO databaseDTO = XPBeanUtils.copyBean(database, DatabaseDTO.class);

        return (WrapperResponse)WrapperResponse.success(databaseDTO);
    }

    /**
     * 查询当前数据库下所有表
     */
    @RequestMapping(value = "/tablesOfDb/{id}", method = {RequestMethod.GET})
    @ApiOperation(value = "查询当前数据库下所有表")
    public WrapperResponse<DatabaseDTO> tablesOfDb(@PathVariable String id) throws Exception{
        DatabaseDO database = databaseService.getById(id);
        if(database != null){
            DatabaseDTO databaseDTO = XPBeanUtils.copyBean(database, DatabaseDTO.class);
            return (WrapperResponse)WrapperResponse.success(DbUtil.getTableNames(databaseDTO));
        }
        return WrapperResponse.fail("数据不存在：" + id, null);
    }

    /**
     * 查询当前表字段
     */
    @RequestMapping(value = "/fieldOfTable", method = {RequestMethod.POST})
    @ApiOperation(value = "查询当前表字段")
    public WrapperResponse<DatabaseDTO> fieldOfTable(String id, String table, String querySql) throws Exception{
        DatabaseDO database = databaseService.getById(id);
        if(database != null){
            DatabaseDTO databaseDTO = XPBeanUtils.copyBean(database, DatabaseDTO.class);
            // 优先自定义SQL
            if(CharSequenceUtil.isNotBlank(querySql)){
                querySql = querySql.trim();
                if(CharSequenceUtil.startWith(querySql, INSERT, true) ||
                        CharSequenceUtil.startWith(querySql, DELETE, true) ||
                        CharSequenceUtil.startWith(querySql, UPDATE, true)){
                    throw new BusinessException("自定义查询语不支持[insert|delete|update]");
                }
                Object obj = DbUtil.getFieldNamesBySql(databaseDTO, querySql);
                return (WrapperResponse)WrapperResponse.success(obj);
            }else{
                List<Map> obj = DbUtil.getFieldNamesByTable(databaseDTO, table);
                List<Map> newMap = new ArrayList<>();
                for (Map map : obj) {
                    Map<String, String> newObj = new HashMap<>();
                    newObj.put("name", map.get("columnName").toString());
                    newObj.put("type", map.get("dataType").toString());
                    newMap.add(newObj);
                }
                return (WrapperResponse)WrapperResponse.success(newMap);
            }
        }else{
            throw new BusinessException("查询数据源为空!!!");
        }
    }

    /**
     * 测试数据源连接
     */
    @RequestMapping(value = "/testConn", method = {RequestMethod.POST})
    @ApiOperation(value = "测试数据源连接")
    public WrapperResponse<DatabaseDTO> testConn(@RequestBody DatabaseDTO database) throws Exception{
        boolean boo = false;
        database.setUrl(DbUtil.convertJdbcUrl(database));
        if(StrUtil.isNotBlank(database.getUrl())){
            boo = DbUtil.testConn(database);
            return boo ? WrapperResponse.success("连接成功", null) : WrapperResponse.fail("连接失败", null);
        }else{
            return WrapperResponse.fail("连接地址为空："+database.getUrl(), null);
        }
    }

    /**
     * 保存
     */
    @RequestMapping(value = "/save",method = {RequestMethod.POST})
    @ApiOperation(value = "保存")
    @SysLog("保存")
    @RequiresPermissions("datasource:database:save")
    public WrapperResponse<DatabaseDTO> save(@RequestBody DatabaseDTO database) throws Exception{
        database.setUrl(DbUtil.convertJdbcUrl(database));
        databaseService.save(DatabaseDO.copyBean(database));
        return (WrapperResponse)WrapperResponse.success(null);
    }

    /**
     * 修改
     */
    @RequestMapping(value = "/update",method = {RequestMethod.POST})
    @ApiOperation(value = "修改")
    @SysLog("修改")
    @RequiresPermissions("datasource:database:update")
    public WrapperResponse<DatabaseDTO> update(@RequestBody DatabaseDTO database) throws Exception{
        database.setUrl(DbUtil.convertJdbcUrl(database));
        databaseService.updateById(DatabaseDO.copyBean(database));
        return (WrapperResponse)WrapperResponse.success(null);
    }

    /**
     * 删除
     */
    @RequestMapping(value = "/deleteBatch",method = {RequestMethod.POST})
    @ApiOperation(value = "批量删除")
    @SysLog("批量删除")
    @RequiresPermissions("datasource:database:deleteBatch")
    public WrapperResponse deleteBatch(@RequestBody String[] ids) throws Exception{
        databaseService.removeByIds(Arrays.asList(ids));

        return WrapperResponse.success(null);
    }
}
